package net.oschina.arvin.sqlbuilder;

import net.oschina.arvin.sqlbuilder.utils.AssertUtil;

/**
 * @author Arvin
 * @time 2017/11/17 10:24
 */
public class DeleteBuilder extends AbstractNotQueryBuilder<DeleteBuilder> {

    /** where 子句 */
    private WhereBuilder whereBuilder;

    /** 如果为 -1 则删除所有满足条件的，默认是 1， 如果要删除所有设置为 -1 */
    private int deleteLimitCount = 1;

    /** 是否允许where子句为空 */
    private boolean allowNullWhereCondition = false;

    /**
     * @param modelType        模型类型
     * @param deleteLimitCount 要删除的数量，如果要限制所有请传一个小于 0 的数字， 如 -1
     * @param whereBuilder     查询条件
     */
    public DeleteBuilder(Class<?> modelType, int deleteLimitCount, WhereBuilder whereBuilder) {
        super(modelType, SqlBuilderType.DELETE);
        AssertUtil.assertNotNull(whereBuilder, "WhereBuilder 不能为空！");
        this.whereBuilder = whereBuilder;
        this.setDeleteLimitCount(deleteLimitCount);
    }

    public boolean isAllowNullWhereCondition() {
        return allowNullWhereCondition;
    }

    public DeleteBuilder setAllowNullWhereCondition(boolean allowNullWhereCondition) {
        this.allowNullWhereCondition = allowNullWhereCondition;
        return this;
    }

    public WhereBuilder getWhereBuilder() {
        return whereBuilder;
    }

    public void setWhereBuilder(WhereBuilder whereBuilder) {
        this.whereBuilder = whereBuilder;
    }

    /**
     * 删除所有符合条件的数据
     *
     * @return
     */
    public DeleteBuilder enabledDeleteAll() {
        this.deleteLimitCount = -1;
        return this;
    }

    @Override
    public String getSql() {
        String sql = super.getSql();
        logUsedSql(sql);
        return sql;
    }

    @Override
    protected String build() {

        StringBuilder sqlBuilder = new StringBuilder("DELETE FROM ").append(getWrapTablename());

        // 添加 WhereBuilder 构造的条件
        boolean isWhereBuilderAppend = lookupAndAppendWhereBuilderCondition(sqlBuilder);

        if (isWhereBuilderAppend) {
            lookupAndAppendUpdateLimitCount(sqlBuilder);
            return sqlBuilder.toString();
        }

        AssertUtil.assertTrue(isAllowNullWhereCondition(),
                "你的删除语句没有设置where子句，太危险了，如果确实需要删除所有符合条件的请调用: DeleteBuilder.setAllowNullWhereCondition(true): \nsql=" + sqlBuilder.toString());

        lookupAndAppendUpdateLimitCount(sqlBuilder);

        return sqlBuilder.toString();

    }

    /**
     * 如果有设置WhereBuilder 就添加过去，并返回 true 表示添加了， 否则返回 false
     *
     * @param sqlBuilder sql 语句构造器
     */
    private boolean lookupAndAppendWhereBuilderCondition(StringBuilder sqlBuilder) {
        if (this.whereBuilder != null && this.whereBuilder.conditionCount() > 0) {
            sqlBuilder.append(" ").append(whereBuilder.getSql());
            addListSqlParams(whereBuilder.getSqlParamList());
            return true;
        }
        return false;
    }

    private boolean lookupAndAppendUpdateLimitCount(StringBuilder sqlBuilder) {
        // 添加Limit
        if (deleteLimitCount > 0) {
            sqlBuilder.append(" LIMIT ").append(deleteLimitCount);
            return true;
        }
        return false;
    }

    @Override
    protected DeleteBuilder self() {
        return this;
    }

    /**
     * 设置要删除的条数， 如果设置为 小于0的 满足条件的都会被删除，默认是只会删除一条
     *
     * @param deleteLimitCount 要删除的数量
     */
    public DeleteBuilder setDeleteLimitCount(int deleteLimitCount) {
        AssertUtil.assertTrue(deleteLimitCount != 0, "要删除的数量不能为0");
        this.deleteLimitCount = deleteLimitCount <= 0 ? -1 : deleteLimitCount;
        return this;
    }
}
